package com.kakarote.oa.common;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.util.TypeUtils;
import com.kakarote.common.field.entity.ModelFieldExtend;
import com.kakarote.core.common.Const;
import com.kakarote.core.common.enums.FieldEnum;
import com.kakarote.core.common.enums.LanguageFieldEnum;
import com.kakarote.core.feign.examine.entity.ExamineFlowFieldUpdateLogBO;
import com.kakarote.core.utils.UserCacheUtil;
import com.kakarote.oa.entity.PO.OaExamineFieldExtend;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
public class ActionRecordUtil {

    @SuppressWarnings("unchecked")
    public static Object parseValue(Object value, Integer type, boolean isNeedStr) {
        if (ObjectUtil.isEmpty(value) && !type.equals(FieldEnum.DETAIL_TABLE.getType())) {
            return isNeedStr ? LanguageFieldEnum.ACTIONRECORD_EMPTY.getFieldFormat() : "";
        }
        FieldEnum fieldEnum = FieldEnum.parse(type);
        switch (fieldEnum) {
            case BOOLEAN_VALUE: {
                return "1".equals(value) ? LanguageFieldEnum.ACTIONRECORD_YES.getFieldFormat() : LanguageFieldEnum.ACTIONRECORD_EMPTY.getFieldFormat();
            }
            case TAG: {
                String eq = "[]";
                if (ObjectUtil.equals(value, eq)) {
                    return LanguageFieldEnum.ACTIONRECORD_EMPTY.getFieldFormat();
                }
                if (value instanceof CharSequence) {
                    value = JSON.parseArray(value.toString());
                }
                if (value instanceof List) {
                    return ((List<?>) value).stream().map(data -> ((Map<String, String>) data).get("name")).collect(Collectors.joining(Const.SEPARATOR));
                }
                return LanguageFieldEnum.ACTIONRECORD_EMPTY.getFieldFormat();
            }
            case AREA_POSITION: {
                StringBuilder stringBuilder = new StringBuilder();
                if (value instanceof CharSequence) {
                    value = JSON.parseArray(value.toString());
                }
                for (Map<String, Object> map : ((List<Map<String, Object>>) value)) {
                    stringBuilder.append(map.get("name")).append(" ");
                }
                return stringBuilder.toString();
            }
            case CURRENT_POSITION: {
                if (value instanceof CharSequence) {
                    value = JSON.parseObject(value.toString());
                }
                return Optional.ofNullable(((Map<String, Object>) value).get("address")).orElse("").toString();
            }
            case DATE_INTERVAL: {
                if (value instanceof Collection) {
                    value = StrUtil.join(Const.SEPARATOR, value);
                }
                return isNeedStr ? value.toString() : value;
            }
            case SINGLE_USER:
            case USER:
                List<String> ids = StrUtil.splitTrim(value.toString(), Const.SEPARATOR);
                return ids.stream().map(id -> UserCacheUtil.getUserName(Long.valueOf(id))).collect(Collectors.joining(Const.SEPARATOR));
            case STRUCTURE:
                List<String> deptIds = StrUtil.splitTrim(value.toString(), Const.SEPARATOR);
                return deptIds.stream().map(id -> UserCacheUtil.getDeptName(Convert.toLong(id))).collect(Collectors.joining(Const.SEPARATOR));
            case DETAIL_TABLE: {
                if (value == null) {
                    value = new ArrayList<>();
                }
                if (value instanceof String) {
                    if ("".equals(value)) {
                        value = new ArrayList<>();
                    } else {
                        value = JSON.parseArray((String) value);
                    }
                }
                List<Map<String, Object>> list = new ArrayList<>();
                JSONArray array = new JSONArray((List<Object>) value);
                for (int i = 0; i < array.size(); i++) {
                    JSONArray objects = array.getJSONArray(i);
                    for (int j = 0; j < objects.size(); j++) {
                        Map<String, Object> map = new HashMap<>();
                        JSONObject data = objects.getJSONObject(j);
                        map.put("name", data.get("name"));
                        map.put("value", parseValue(data.get("value"), data.getInteger("type"), false));
                        list.add(map);
                    }
                }
                return list;
            }
            default:
                return isNeedStr ? value.toString() : value;
        }

    }

    /**
     * CRM模块导出这个方法的时候，已经经过es查询后处理过，但是log没有es所以这里 user、structure 再处理一下
     *
     * @param value
     * @param type
     * @param isNeedStr
     * @return
     */
    public static Object parseExportValue(Object value, Integer type, boolean isNeedStr) {
        if (ObjectUtil.isEmpty(value) && !type.equals(FieldEnum.DETAIL_TABLE.getType())) {
            return isNeedStr ? LanguageFieldEnum.ACTIONRECORD_EMPTY.getModule() : "";
        }
        FieldEnum fieldEnum = FieldEnum.parse(type);
        switch (fieldEnum) {
            case USER: {
                List<String> names = UserCacheUtil.getUserNameList(Arrays.stream(value.toString().split(Const.SEPARATOR)).map(TypeUtils::castToLong).collect(Collectors.toList()));
                return String.join(Const.SEPARATOR, names);
            }
            case STRUCTURE: {
                List<String> names = UserCacheUtil.getDeptNameList(Arrays.stream(value.toString().split(Const.SEPARATOR)).map(TypeUtils::castToLong).collect(Collectors.toList()));
                return String.join(Const.SEPARATOR, names);
            }
            case BOOLEAN_VALUE: {
                return "1".equals(value) ? LanguageFieldEnum.ACTIONRECORD_YES.getModule() : LanguageFieldEnum.ACTIONRECORD_NO.getModule();
            }
            case TAG: {
                if (value instanceof CharSequence) {
                    value = JSON.parseArray(value.toString());
                }
                if (value instanceof List) {
                    return ((List<?>) value).stream().map(data -> ((Map<String, String>) data).get("name")).collect(Collectors.joining(Const.SEPARATOR));
                }
                return "";
            }
            case AREA_POSITION: {
                StringBuilder stringBuilder = new StringBuilder();
                if (value instanceof CharSequence) {
                    value = JSON.parseArray(value.toString());
                }
                for (Map<String, Object> map : ((List<Map<String, Object>>) value)) {
                    stringBuilder.append(map.get("name")).append(" ");
                }
                return stringBuilder.toString();
            }
            case CURRENT_POSITION: {
                if (value instanceof CharSequence) {
                    value = JSON.parseObject(value.toString());
                }
                return Optional.ofNullable(((Map<String, Object>) value).get("address")).orElse("").toString();
            }
            case DATE_INTERVAL: {
                if (value instanceof Collection) {
                    value = StrUtil.join(Const.SEPARATOR, value);
                }
                return isNeedStr ? value.toString() : value;
            }
            case SINGLE_USER:
            case DETAIL_TABLE: {
                if (value == null) {
                    value = new ArrayList<>();
                }
                if (value instanceof String) {
                    if ("".equals(value)) {
                        value = new ArrayList<>();
                    } else {
                        value = JSON.parseArray((String) value);
                    }
                }
                List<Map<String, Object>> list = new ArrayList<>();
                JSONArray array = new JSONArray((List<Object>) value);
                for (int i = 0; i < array.size(); i++) {
                    JSONArray objects = array.getJSONArray(i);
                    for (int j = 0; j < objects.size(); j++) {
                        Map<String, Object> map = new HashMap<>();
                        JSONObject data = objects.getJSONObject(j);
                        map.put("name", data.get("name"));
                        map.put("value", parseValue(data.get("value"), data.getInteger("type"), false));
                        list.add(map);
                    }
                }
                return list;
            }
            default:
                return isNeedStr ? value.toString() : value;
        }

    }

    @SuppressWarnings("unchecked")
    public static void parseDetailTable(Object oldFieldValue, Object newFieldValue, String name, Integer type, List<String> textList) {
        List<Map<String, Object>> oldFieldValues = (List<Map<String, Object>>) ActionRecordUtil.parseValue(oldFieldValue, type, false);
        List<Map<String, Object>> newFieldValues = (List<Map<String, Object>>) ActionRecordUtil.parseValue(newFieldValue, type, false);
        int size = Math.max(oldFieldValues.size(), newFieldValues.size());
        for (int i = 0; i < size; i++) {
            Object oldValue = oldFieldValues.size() > i ? oldFieldValues.get(i).get("value") : "";
            Object newValue = newFieldValues.size() > i ? newFieldValues.get(i).get("value") : "";
            if (!Objects.equals(oldValue, newValue)) {
                oldValue = "".equals(oldValue) ? LanguageFieldEnum.ACTIONRECORD_EMPTY.getModule() : oldValue;
                newValue = "".equals(newValue) ? LanguageFieldEnum.ACTIONRECORD_EMPTY.getModule() : newValue;
                Map<String, Object> map = oldFieldValues.size() >= newFieldValues.size() ? oldFieldValues.get(i) : newFieldValues.get(i);
                textList.add("" + name + " " + map.get("name") + " " + oldValue + "修改为" + newValue + "。");
            }
        }
    }

    public static Object transParseValue(Object value) {
        if (ObjectUtil.isEmpty(value)) {
            return LanguageFieldEnum.ACTIONRECORD_EMPTY.getFieldFormat();
        }
        if ("空".equals(StrUtil.toString(value))) {
            return LanguageFieldEnum.ACTIONRECORD_EMPTY.getFieldFormat();
        }
        if ("是".equals(StrUtil.toString(value))) {
            return LanguageFieldEnum.ACTIONRECORD_YES.getFieldFormat();
        }
        if ("否".equals(StrUtil.toString(value))) {
            return LanguageFieldEnum.ACTIONRECORD_NO.getFieldFormat();
        }
        return value;
    }

    public static void getRecord(List<String> textList, List<String> transList, ExamineFlowFieldUpdateLogBO log) {
        String oldValue = (String) ActionRecordUtil.parseValue(log.getOldValue(), log.getType(), false);
        String newValue = (String) ActionRecordUtil.parseValue(log.getNewValue(), log.getType(), false);

        Map<String, Object> oldObj = new HashMap<>();
        oldObj.put(log.getFieldName(), oldValue);
        Map<String, Object> newObj = new HashMap<>();
        newObj.put(log.getFieldName(), newValue);

        if (ObjectUtil.isEmpty(oldValue)) {
            oldValue = "空";
        }
        if (ObjectUtil.isEmpty(newValue)) {
            newValue = "空";
        }
        textList.add("将" + log.getName() + " 由" + oldValue + "修改为" + newValue + "。");
    }

    public static String formatKey(OaEnum oaEnum, String name) {
        //customField.contacts.nextTime
        String labelName = oaEnum.getTableName();
        if (oaEnum == OaEnum.RETURN_VISIT) {
            labelName = "visit";
        }
        return "{customField." + labelName + "." + name + "}";
    }

    public static List<OaExamineFieldExtend> queryOaExamineFieldExtend(Integer type) {
        List<ModelFieldExtend> fieldExtendList = new ArrayList<>();
        if (FieldEnum.EXAMINE_CAUSE.getType().equals(type)) {
            //差旅
            fieldExtendList.add(new ModelFieldExtend("出发城市", "startAddress", FieldEnum.TEXT));
            fieldExtendList.add(new ModelFieldExtend("目的城市", "endAddress", FieldEnum.TEXT));
            fieldExtendList.add(new ModelFieldExtend("开始时间", "startTime", FieldEnum.DATETIME));
            fieldExtendList.add(new ModelFieldExtend("结束时间", "endTime", FieldEnum.DATETIME));
            fieldExtendList.add(new ModelFieldExtend("交通费", "traffic", FieldEnum.FLOATNUMBER));
            fieldExtendList.add(new ModelFieldExtend("住宿费", "stay", FieldEnum.FLOATNUMBER));
            fieldExtendList.add(new ModelFieldExtend("餐饮费", "diet", FieldEnum.FLOATNUMBER));
            fieldExtendList.add(new ModelFieldExtend("其他费用", "other", FieldEnum.FLOATNUMBER));
            fieldExtendList.add(new ModelFieldExtend("合计", "money", FieldEnum.FLOATNUMBER));
            fieldExtendList.add(new ModelFieldExtend("费用明细描述", "description", FieldEnum.TEXTAREA));
            fieldExtendList.add(new ModelFieldExtend("发票", "file", FieldEnum.FILE));
        }
        //出差
        if (FieldEnum.BUSINESS_CAUSE.getType().equals(type)) {
            fieldExtendList.add(new ModelFieldExtend("交通工具", "vehicle", FieldEnum.SELECT));
            fieldExtendList.add(new ModelFieldExtend("单程往返", "trip", FieldEnum.SELECT));
            fieldExtendList.add(new ModelFieldExtend("出发城市", "startAddress", FieldEnum.TEXT));
            fieldExtendList.add(new ModelFieldExtend("目的城市", "endAddress", FieldEnum.TEXT));
            fieldExtendList.add(new ModelFieldExtend("开始时间", "startTime", FieldEnum.DATETIME));
            fieldExtendList.add(new ModelFieldExtend("结束时间", "endTime", FieldEnum.DATETIME));
            fieldExtendList.add(new ModelFieldExtend("时长", "duration", FieldEnum.NUMBER));
            fieldExtendList.add(new ModelFieldExtend("备注", "description", FieldEnum.FLOATNUMBER));
        }
        return fieldExtendList.stream().map(fieldExtend -> {
            fieldExtend.setFieldType(1);
            return BeanUtil.copyProperties(fieldExtend, OaExamineFieldExtend.class);
        }).collect(Collectors.toList());
    }


    public static void parseCause(String oldValue, String newValue, String name, Integer type, List<String> textList) {
        List<OaExamineFieldExtend> fieldExtendList = new ArrayList<>();
        if (FieldEnum.EXAMINE_CAUSE.getType().equals(type) || FieldEnum.BUSINESS_CAUSE.getType().equals(type)) {
            fieldExtendList = ActionRecordUtil.queryOaExamineFieldExtend(type);
        }

        List<Map<String, Object>> oldFieldValues = new ArrayList<>();
        List<Map<String, Object>> newFieldValues = new ArrayList<>();


        if (ObjectUtil.isNotEmpty(oldValue)) {
            List<Map> list = JSON.parseArray(oldValue, Map.class);

            for (Map data : list) {
                for (OaExamineFieldExtend fieldExtend : fieldExtendList) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("name", fieldExtend.getName());
                    map.put("value", data.get(fieldExtend.getFieldName()));
                    oldFieldValues.add(map);
                }
            }
        }

        if (ObjectUtil.isNotEmpty(newValue)) {
            List<Map> list = JSON.parseArray(newValue, Map.class);
            for (Map data : list) {
                for (OaExamineFieldExtend fieldExtend : fieldExtendList) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("name", fieldExtend.getName());
                    map.put("value", data.get(fieldExtend.getFieldName()));
                    newFieldValues.add(map);
                }
            }
        }

        int size = Math.max(oldFieldValues.size(), newFieldValues.size());
        for (int i = 0; i < size; i++) {
            Object oldValue1 = oldFieldValues.size() > i ? oldFieldValues.get(i).get("value") : "";
            Object newValue1 = newFieldValues.size() > i ? newFieldValues.get(i).get("value") : "";
            if (!Objects.equals(oldValue1, newValue1)) {
                oldValue1 = "".equals(oldValue1) ? LanguageFieldEnum.ACTIONRECORD_EMPTY.getModule() : oldValue1;
                newValue1 = "".equals(newValue1) ? LanguageFieldEnum.ACTIONRECORD_EMPTY.getModule() : newValue1;
                Map<String, Object> map = oldFieldValues.size() >= newFieldValues.size() ? oldFieldValues.get(i) : newFieldValues.get(i);
                textList.add(name + " " + map.get("name") + " " + oldValue1 + "修改为" + newValue1 + "。");
            }
        }

    }
}